package com.linkgie.galaxyframework.utils.io;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.Manifest;

import com.linkgie.galaxyframework.utils.IOStatusException;
import com.linkgie.galaxyframework.utils.TextUtils;

class JarFileSystemImpl extends ZipFileSystemImpl implements JarFileSystem {

	private static final String MENIFEST_FILE_PATH = "META-INF/MANIFEST.MF";
	
	private static final String CLASSPATH_MANIFEST_KEY = "Class-Path";

	private static final String defaultManifestVersion = "1.0";

	private Manifest manifest;

	private boolean manifestChanged;

	public JarFileSystemImpl(String file) {
		super(file);
	}

	public JarFileSystemImpl(File file) {
		super(file);
	}

	@Override
	protected void postInitialized() {
		try (InputStream in = read(MENIFEST_FILE_PATH)) {
			this.manifest = new Manifest(in);
		} catch (IOException e) {
			throw new IOStatusException(e.getMessage(), e);
		}
	}

	@Override
	protected String getUriScheme() {
		return "jar:";
	}

	@Override
	public String setManifestValue(String propertyName, String propertyValue) {
		String previousValue = this.manifest.getMainAttributes().putValue(propertyName, propertyValue);
		this.manifestChanged = true;
		return previousValue;
	}

	@Override
	public String getManifestValue(String propertyName) {
		return this.manifest.getMainAttributes().getValue(propertyName);
	}

	@Override
	public String removeManifestValue(String propertyName) {
		return (String) this.manifest.getMainAttributes().remove(new Attributes.Name(propertyName));
	}

	@Override
	protected void beforeClose() throws IOException {
		Manifest mf = this.manifest;
		if (mf != null && this.manifestChanged) {
			saveManifest(mf);
		}
	}

	protected void saveManifest(Manifest mf) throws IOException {
		// 必须写入版本，否则不会输出任何内容；
		if (!mf.getMainAttributes().containsKey(Name.MANIFEST_VERSION)) {
			mf.getMainAttributes().putValue(Name.MANIFEST_VERSION.toString(), defaultManifestVersion);
		}
		try (OutputStream out = openOrCreateEntry(MENIFEST_FILE_PATH)) {
			mf.write(out);
			out.flush();
		}

		this.manifestChanged = false;
	}

	@Override
	protected void afterClose() throws IOException {
		this.manifest = null;
	}

	@Override
	public String[] resolveManifestClasspaths() {
		if (manifest == null) {
			throw new IllegalStateException("This jar file is closed!");
		}
		String classpathsLines = getManifestValue(CLASSPATH_MANIFEST_KEY);
		if (classpathsLines == null) {
			return TextUtils.EMPTY_ARRAY;
		}
		// 每一项类路径都按照空格分隔； 
		String[] classpaths = classpathsLines.split(" ");
		return classpaths;
	}
}